package lifeOfAFish.scenegraph;

import java.io.File;

import javax.media.opengl.GL;

import com.sun.opengl.util.texture.Texture;
import com.sun.opengl.util.texture.TextureIO;

public abstract class sgGeometry extends sgNode {

	protected sgMaterial m_material = new sgMaterial();
	protected sgColor m_color;
	protected boolean m_addedToBlender = false;
	protected boolean m_opaque = true;
	protected boolean m_force = false;
	protected float[] m_modelView = new float[16];
	protected boolean m_active = true;
	protected Texture m_tex = null;
	
	public sgVec3 m_bbMin;
	public sgVec3 m_bbMax;
	
	/**
	 * render method (this should probably be abstract)
	 */
	public void render()
	{
		m_material.apply();
		
		// compute bounding box
		m_bbMin = computeGlobalCoords(new sgVec3(-0.25f, -0.25f, -0.25f));
		m_bbMax = computeGlobalCoords(new sgVec3(0.25f, 0.25f, 0.25f));
		
		// save the modelview matrix
		sgGlobals.gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, m_modelView, 0);
		
		// temp, add this object to the geometry blender
		if (!isOpaque()){
			sgGeomBlender.getInstance().addGeom(this);
		}
		
		// if not in the blender, or being forced, draw
		if (!this.inBlender() || this.m_force) {
//			this.bindTexture();
			if(this.m_active) draw();
//			this.unbindTexture();
		}
	};
	
	/**
	 * bind texture to geometry
	 */
	public void bindTexture()
	{
		GL gl = sgGlobals.gl;
		if(m_tex != null) {
			gl.glEnable(GL.GL_TEXTURE_2D);
			gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE);
			gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
			gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
			m_tex.enable(); 
			m_tex.bind();
		}
	}
	
	/**
	 * unbind texture from geometry
	 */
	public void unbindTexture()
	{
		if(m_tex != null){
			m_tex.disable();
			sgGlobals.gl.glDisable(GL.GL_TEXTURE_2D);
		}
	}
	
	/**
	 * load a texture
	 * @param filename name of texture
	 */
	public void loadTexture(String filename)
	{
		try {
	     m_tex = TextureIO.newTexture(new File(filename), false);
		}catch (Exception e)
		{
			System.out.println("error loading texture: "+filename);
			System.out.println(e);
		}
	}
	
	// set/get material
	public void setMaterial(sgMaterial mat) {m_material = mat;}
	public sgMaterial getMaterial() {return m_material;}
	
	// set/get color
	public void setColor(sgColor col) {m_color = col;}
	public sgColor getColor() {return m_color;}
	
	// set/get active
	public void setActive(boolean f) { m_active = f; }
	public boolean isActive() { return m_active; }
	
	// push current lighting attributes as well
	protected void push () 
	{
		sgGlobals.gl.glPushAttrib(GL.GL_LIGHTING_BIT);
	}
	
	// pop current lighting attributes as well
	protected void pop () 
	{
		sgGlobals.gl.glPopAttrib();
	}
	
	// add to the blender
	protected void addToBlender(){
		this.m_addedToBlender = true;
	}
	
	// remove from blender
	protected void removeFromBlender(){
		this.m_addedToBlender = false;
	}
	
	// are we in the blender
	protected boolean inBlender(){
		return m_addedToBlender;
	}
	
	public void setOpaque(boolean flag){
		m_opaque = flag;
	}
	
	protected boolean isOpaque(){
		return m_opaque;
	}
	
	protected void setForce(boolean flag){
		m_force = flag;
	}
	
	/**
	 * Return the modelview matrix
	 * @return a 16 element float array
	 */
	public float[] getModelView()
	{
		return m_modelView;
	}
	
	/**
	 * draw the geometry. left to children.
	 */
	protected abstract void draw();
	
	
	/**
	 * Calculate the bounding box of this geometry
	 */
	public abstract float[] getBoundingBox();
	
	/**
	 * Get the global bounding box
	 */
	public sgVec3[] getGlobalBoundingBox(){
		
		// retrieve local bounding box corners in vector format
		float[] bb = this.getBoundingBox();
		sgVec3[] verts = new sgVec3[8];
		int index = 0;
		for (int a = 0; a < 2; a++)
			for (int b = 0; b < 2; b++)
				for(int c = 0; c < 2; c++){
					verts[index] = new sgVec3(bb[a%2], bb[2+b%2], bb[4+c%2]);
					verts[index] = this.computeGlobalCoords(verts[index]);
					index++;
				}
		
		return verts;
	}                                 

}
